package com.wshoto.ocean.service.common.service.impl;

import com.baomidou.mybatisplus.core.conditions.*;
import com.baomidou.mybatisplus.core.enums.*;
import com.baomidou.mybatisplus.core.mapper.*;
import com.baomidou.mybatisplus.core.metadata.*;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.*;
import com.baomidou.mybatisplus.extension.toolkit.*;
import com.wshoto.framework.common.util.*;
import com.wshoto.mybatis.autoconfigure.util.*;
import com.wshoto.ocean.service.common.service.*;
import org.apache.ibatis.binding.*;
import org.apache.ibatis.session.*;
import org.mybatis.spring.*;
import org.springframework.beans.*;
import org.springframework.context.*;
import org.springframework.stereotype.*;
import org.springframework.transaction.annotation.*;

import javax.annotation.*;
import java.io.*;
import java.util.*;
import java.util.stream.*;

/**
 * 通用CRUD操作实现
 *
 * @author Lee
 */
@Service("simpleGenericDataBaseService")
public class SimpleGenericDataBaseServiceImpl implements SimpleGenericDataBaseService, ApplicationContextAware {

    private final static String SUFFIX_NAME = "Mapper";

    @Resource
    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    protected boolean retBool(Integer result) {
        return SqlHelper.retBool(result);
    }

    protected SqlSession sqlSessionBatch(Class clazz) {
        return SqlHelper.sqlSessionBatch(clazz);
    }

    protected void closeSqlSession(SqlSession sqlSession, Class clazz) {
        SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(clazz));
    }

    protected String sqlStatement(SqlMethod sqlMethod, Class clazz) {
        return SqlHelper.table(clazz).getSqlStatement(sqlMethod.getMethod());
    }

    @Override
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public <T> boolean save(T entity) {
        Assert.isTrue(!ObjectUtils.isEmpty(entity), "entity must not be null");
        return this.retBool(((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(entity.getClass().getSimpleName()).concat(SUFFIX_NAME))).insert(entity));
    }

    @Override
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public <T> boolean saveBatch(Collection<T> entityList, int batchSize, Class clazz) {
        Assert.isTrue(!CollectionUtils.isEmpty(entityList), "Error: entityList must not be empty");
        int i = 0;
        String sqlStatement = this.sqlStatement(SqlMethod.INSERT_ONE, clazz);
        SqlSession batchSqlSession = this.sqlSessionBatch(clazz);
        Throwable var6 = null;

        try {
            for (Iterator var7 = entityList.iterator(); var7.hasNext(); ++i) {
                T anEntityList = (T) var7.next();
                batchSqlSession.insert(sqlStatement, anEntityList);
                if (i >= 1 && i % batchSize == 0) {
                    batchSqlSession.flushStatements();
                }
            }

            batchSqlSession.flushStatements();
            return true;
        } catch (Throwable var16) {
            var6 = var16;
            throw var16;
        } finally {
            if (batchSqlSession != null) {
                if (var6 != null) {
                    try {
                        batchSqlSession.close();
                    } catch (Throwable var15) {
                        var6.addSuppressed(var15);
                    }
                } else {
                    batchSqlSession.close();
                }
            }

        }
    }

    @Override
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public <T> boolean saveOrUpdate(T entity) {
        if (null == entity) {
            return false;
        } else {
            Class<?> cls = entity.getClass();
            TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
            if (null != tableInfo && StringUtils.isNotBlank(tableInfo.getKeyProperty())) {
                Object idVal = ReflectionKit.getFieldValue(entity, tableInfo.getKeyProperty());
                return !StringUtils.checkValNull(idVal) && !Objects.isNull(this.getById((Serializable) idVal, entity.getClass())) ? this.updateById(entity) : this.save(entity);
            } else {
                throw ExceptionUtils.mpe("Error:  Can not execute. Could not find @TableId.", new Object[0]);
            }
        }
    }

    @Override
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public <T> boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize, Class clazz) {
        Assert.isTrue(!CollectionUtils.isEmpty(entityList), "Error: entityList must not be empty");
        TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);
        int i = 0;
        SqlSession batchSqlSession = this.sqlSessionBatch(clazz);
        Throwable var7 = null;

        try {
            Iterator var8 = entityList.iterator();

            while (var8.hasNext()) {
                T anEntityList = (T) var8.next();
                if (null == tableInfo || StringUtils.isBlank(tableInfo.getKeyProperty())) {
                    throw ExceptionUtils.mpe("Error:  Can not execute. Could not find @TableId.", new Object[0]);
                }
                Object idVal = ReflectionKit.getFieldValue(anEntityList, tableInfo.getKeyProperty());
                if (!StringUtils.checkValNull(idVal) && !Objects.isNull(this.getById((Serializable) idVal, clazz))) {
                    MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap();
                    param.put("et", anEntityList);
                    batchSqlSession.update(this.sqlStatement(SqlMethod.UPDATE_BY_ID, clazz), param);
                } else {
                    batchSqlSession.insert(this.sqlStatement(SqlMethod.INSERT_ONE, clazz), anEntityList);
                }

                if (i >= 1 && i % batchSize == 0) {
                    batchSqlSession.flushStatements();
                }

                ++i;
                batchSqlSession.flushStatements();
            }
        } catch (Throwable var19) {
            var7 = var19;
            throw var19;
        } finally {
            if (batchSqlSession != null) {
                if (var7 != null) {
                    try {
                        batchSqlSession.close();
                    } catch (Throwable var18) {
                        var7.addSuppressed(var18);
                    }
                } else {
                    batchSqlSession.close();
                }
            }

        }
        return true;
    }

    @Override
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public boolean deleteById(Serializable id, Class clazz) {
        Assert.isTrue(!ObjectUtils.isEmpty(id), "id must not be null");
        return SqlHelper.retBool(((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(clazz.getSimpleName()).concat(SUFFIX_NAME))).deleteById(id));
    }

    @Override
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public boolean deleteByMap(Map<String, Object> columnMap, Class clazz) {
        Assert.isTrue(!CollectionUtils.isEmpty(columnMap), "removeByMap columnMap is empty.", new Object[0]);
        return SqlHelper.retBool(((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(clazz.getSimpleName()).concat(SUFFIX_NAME))).deleteByMap(columnMap));
    }

    @Override
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public <T> boolean delete(Wrapper<T> wrapper) {
        Assert.isTrue(WrapperUtils.nonEmptyOfEntity(wrapper), "未填充实体对象");
        return SqlHelper.retBool(((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(wrapper.getEntity().getClass().getSimpleName()).concat(SUFFIX_NAME))).delete(wrapper));
    }

    @Override
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public <T> boolean deleteByIds(Collection<? extends Serializable> idList, Class clazz) {
        Assert.isTrue(!CollectionUtils.isEmpty(idList), "idList不能为空");
        return SqlHelper.retBool(((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(clazz.getSimpleName()).concat(SUFFIX_NAME))).deleteBatchIds(idList));
    }

    @Override
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public <T> boolean updateById(T entity) {
        Class<?> cls = entity.getClass();
        TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
        Assert.isTrue(!ObjectUtils.isEmpty(entity), "entity must not be null");
        Assert.isTrue(!ObjectUtils.isEmpty(ReflectionKit.getFieldValue(entity, tableInfo.getKeyProperty())), "id must not be null");
        return this.retBool(((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(entity.getClass().getSimpleName()).concat(SUFFIX_NAME))).updateById(entity));
    }

    @Override
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public <T> boolean update(T entity, Wrapper<T> updateWrapper) {
        Assert.isTrue(!ObjectUtils.isEmpty(entity), "entity must not be null");
        return this.retBool(((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(entity.getClass().getSimpleName()).concat(SUFFIX_NAME))).update(entity, updateWrapper));
    }

    @Override
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public <T> boolean updateBatchById(Collection<T> entityList, int batchSize, Class clazz) {
        Assert.isTrue(!CollectionUtils.isEmpty(entityList), "Error: entityList must not be empty");
        int i = 0;
        String sqlStatement = this.sqlStatement(SqlMethod.UPDATE_BY_ID, clazz);
        SqlSession batchSqlSession = this.sqlSessionBatch(clazz);
        Throwable var6 = null;

        try {
            for (Iterator var7 = entityList.iterator(); var7.hasNext(); ++i) {
                T anEntityList = (T) var7.next();
                MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap();
                param.put("et", anEntityList);
                batchSqlSession.update(sqlStatement, param);
                if (i >= 1 && i % batchSize == 0) {
                    batchSqlSession.flushStatements();
                }
            }

            batchSqlSession.flushStatements();
            return true;
        } catch (Throwable var17) {
            var6 = var17;
            throw var17;
        } finally {
            if (batchSqlSession != null) {
                if (var6 != null) {
                    try {
                        batchSqlSession.close();
                    } catch (Throwable var16) {
                        var6.addSuppressed(var16);
                    }
                } else {
                    batchSqlSession.close();
                }
            }

        }
    }

    @Override
    public <T> T getById(Serializable id, Class clazz) {
        Assert.isTrue(!ObjectUtils.isEmpty(id), "id must not be null");
        return (T) ((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(clazz.getSimpleName()).concat(SUFFIX_NAME))).selectById(id);
    }

    @Override
    public <T> Collection<T> listByIds(Collection<? extends Serializable> idList, Class clazz) {
        Assert.isTrue(!CollectionUtils.isEmpty(idList), "idList must not be null");
        return ((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(clazz.getSimpleName()).concat(SUFFIX_NAME))).selectBatchIds(idList);
    }

    @Override
    public <T> Collection<T> listByMap(Map<String, Object> columnMap, Class clazz) {
        Assert.isTrue(!CollectionUtils.isEmpty(columnMap), "columnMap must not be null");
        return ((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(clazz.getSimpleName()).concat(SUFFIX_NAME))).selectByMap(columnMap);
    }

    @Override
    public <T> T getOne(Wrapper<T> queryWrapper, boolean throwEx) {
        Assert.isTrue(WrapperUtils.nonEmptyOfEntity(queryWrapper), "未填充实体对象");
//        return throwEx ? (T) ((BaseMapper)applicationContext.getBean(CommonUtils.LowerFirst(queryWrapper.getEntity().getClass().getSimpleName()).concat(SUFFIX_NAME))).selectOne(queryWrapper) : null;
        return throwEx ? (T) ((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(queryWrapper.getEntity().getClass().getSimpleName()).concat(SUFFIX_NAME))).selectOne(queryWrapper) : WrapperUtils.getObject((List<T>) ((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(queryWrapper.getEntity().getClass().getSimpleName()).concat(SUFFIX_NAME))).selectList(queryWrapper));
    }

    @Override
    public <T> Map<String, Object> getMap(Wrapper<T> queryWrapper) {
        Assert.isTrue(WrapperUtils.nonEmptyOfEntity(queryWrapper), "未填充实体对象");
        return (Map) WrapperUtils.getObject(((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(queryWrapper.getEntity().getClass().getSimpleName()).concat(SUFFIX_NAME))).selectMaps(queryWrapper));
    }

    @Override
    public <T> int count(Wrapper<T> queryWrapper) {
        Assert.isTrue(WrapperUtils.nonEmptyOfEntity(queryWrapper), "未填充实体对象");
        return SqlHelper.retCount(((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(queryWrapper.getEntity().getClass().getSimpleName()).concat(SUFFIX_NAME))).selectCount(queryWrapper));
    }

    @Override
    public <T> List<T> list(Wrapper<T> queryWrapper) {
        Assert.isTrue(WrapperUtils.nonEmptyOfEntity(queryWrapper), "未填充实体对象");
        return ((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(queryWrapper.getEntity().getClass().getSimpleName()).concat(SUFFIX_NAME))).selectList(queryWrapper);
    }

    @Override
    public <T> IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper) {
        Assert.isTrue(WrapperUtils.nonEmptyOfEntity(queryWrapper), "未填充实体对象");
        return ((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(queryWrapper.getEntity().getClass().getSimpleName()).concat(SUFFIX_NAME))).selectPage(page, queryWrapper);
    }

    @Override
    public <T> List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper) {
        Assert.isTrue(WrapperUtils.nonEmptyOfEntity(queryWrapper), "未填充实体对象");
        return ((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(queryWrapper.getEntity().getClass().getSimpleName()).concat(SUFFIX_NAME))).selectMaps(queryWrapper);
    }

    @Override
    public <T> List<T> listObjs(Wrapper<T> queryWrapper) {
        Assert.isTrue(WrapperUtils.nonEmptyOfEntity(queryWrapper), "未填充实体对象");
        return (List) ((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(queryWrapper.getEntity().getClass().getSimpleName()).concat(SUFFIX_NAME))).selectObjs(queryWrapper).stream().filter(Objects::nonNull).collect(Collectors.toList());
    }

    @Override
    public <T> IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper) {
        Assert.isTrue(WrapperUtils.nonEmptyOfEntity(queryWrapper), "未填充实体对象");
        return ((BaseMapper) applicationContext.getBean(CommonUtils.LowerFirst(queryWrapper.getEntity().getClass().getSimpleName()).concat(SUFFIX_NAME))).selectMapsPage(page, queryWrapper);
    }

}
